package com.zziq.cloudpicturebank.service.impl;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zziq.cloudpicturebank.exception.BusinessException;
import com.zziq.cloudpicturebank.exception.ErrorCode;
import com.zziq.cloudpicturebank.exception.ThrowUtils;
import com.zziq.cloudpicturebank.model.dto.categorytag.CategoryTagAddRequest;
import com.zziq.cloudpicturebank.model.dto.categorytag.CategoryTagQueryRequest;
import com.zziq.cloudpicturebank.model.dto.categorytag.CategoryTagUpdateRequest;
import com.zziq.cloudpicturebank.model.entity.CategoryTag;
import com.zziq.cloudpicturebank.model.entity.Picture;
import com.zziq.cloudpicturebank.model.entity.Space;
import com.zziq.cloudpicturebank.model.entity.User;
import com.zziq.cloudpicturebank.model.enums.CategoryTagEnum;
import com.zziq.cloudpicturebank.service.CategoryTagService;
import com.zziq.cloudpicturebank.mapper.CategoryTagMapper;
import com.zziq.cloudpicturebank.service.PictureService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author Mr·张
 * @description 针对表【category_tag(分类标签表)】的数据库操作Service实现
 * @createDate 2025-03-08 22:43:29
 */
@Service
public class CategoryTagServiceImpl extends ServiceImpl<CategoryTagMapper, CategoryTag>
        implements CategoryTagService {
    @Resource
    private PictureService pictureService;


    /**
     * 添加分类标签
     *
     * @param categoryTagAddRequest
     * @param loginUser
     * @return
     */
    @Override
    public long addCategoryTag(CategoryTagAddRequest categoryTagAddRequest, User loginUser) {
        //校验参数
        Integer type = categoryTagAddRequest.getType();
        if (type == null ||
                (!type.equals(CategoryTagEnum.CATEGORY.getValue()) && !type.equals(CategoryTagEnum.TAG.getValue()))) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "分类标签为空 或类型错误");
        }
        String name = categoryTagAddRequest.getName();
        ThrowUtils.throwIf(StrUtil.isEmpty(name), ErrorCode.PARAMS_ERROR, "分类标签名称为空");
        //校验是否已存在该分类标签
        boolean isExists;
        if (type.equals(CategoryTagEnum.CATEGORY.getValue())) {
            isExists = this.lambdaQuery()
                    .eq(CategoryTag::getType, CategoryTagEnum.CATEGORY.getValue())
                    .eq(CategoryTag::getName, name)
                    .exists();
            ThrowUtils.throwIf(isExists, ErrorCode.OPERATION_ERROR, "新增失败，分类已存在");
        } else {
            isExists = this.lambdaQuery()
                    .eq(CategoryTag::getType, CategoryTagEnum.TAG.getValue())
                    .eq(CategoryTag::getName, name)
                    .exists();
            ThrowUtils.throwIf(isExists, ErrorCode.OPERATION_ERROR, "新增失败，标签已存在");
        }
        //封装参数
        CategoryTag categoryTag = new CategoryTag();
        categoryTag.setName(name);
        categoryTag.setType(type);
        categoryTag.setUserId(loginUser.getId());
        //插入数据库
        boolean res = this.save(categoryTag);
        ThrowUtils.throwIf(!res, ErrorCode.OPERATION_ERROR, "分类标签添加失败,数据库添加失败！");
        //返回id
        return categoryTag.getId();
    }

    /**
     * 删除分类标签
     *
     * @param categoryTag
     */
    @Override
    public void deleteCategoryTagById(CategoryTag categoryTag) {
        //校验参数
        Integer categoryTagType = categoryTag.getType();
        if (categoryTagType == null ||
                (!categoryTagType.equals(CategoryTagEnum.CATEGORY.getValue())
                        && !categoryTagType.equals(CategoryTagEnum.TAG.getValue()))) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "分类标签为空 或类型错误");
        }

        boolean res;
        Long categoryTagId = categoryTag.getId();

        //判断是标签/分类
        //1.标签
        if (categoryTagType.equals(CategoryTagEnum.TAG.getValue())) {
            //如果是标签直接删除即可
            res = this.removeById(categoryTagId);
            ThrowUtils.throwIf(!res, ErrorCode.OPERATION_ERROR, "标签删除失败,数据库操作失败");
        }
        //2.分类
        else {
            //校验分类是否可以删除
            validCategoryCanUpdateWithDelete(categoryTag);
            res = this.removeById(categoryTagId);
            ThrowUtils.throwIf(!res, ErrorCode.OPERATION_ERROR, "标签删除失败,数据库操作失败");
        }
    }

    /**
     * 更新分类标签
     *
     * @param categoryTagUpdateRequest
     */
    @Override
    public void updateCategoryTag(CategoryTagUpdateRequest categoryTagUpdateRequest) {
        // 判断是否存在
        long id = categoryTagUpdateRequest.getId();
        CategoryTag oldCategoryTag = this.getById(id);
        ThrowUtils.throwIf(oldCategoryTag == null, ErrorCode.NOT_FOUND_ERROR);

        //校验参数
        Integer categoryTagType = oldCategoryTag.getType();
        if (categoryTagType == null ||
                (!categoryTagType.equals(CategoryTagEnum.CATEGORY.getValue())
                        && !categoryTagType.equals(CategoryTagEnum.TAG.getValue()))) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "分类标签为空 或类型错误");
        }

        // 将实体类和 DTO 进行转换
        CategoryTag newCategoryTag = new CategoryTag();
        BeanUtils.copyProperties(categoryTagUpdateRequest, newCategoryTag);
        newCategoryTag.setEditTime(new Date());
        boolean res;
        //判断是标签/分类
        //1.标签
        if (categoryTagType.equals(CategoryTagEnum.TAG.getValue())) {
            //如果是标签直接删除即可
            res = this.updateById(newCategoryTag);
            ThrowUtils.throwIf(!res, ErrorCode.OPERATION_ERROR, "标签删除失败,数据库操作失败");
        }
        //2.分类
        else {
            validCategoryCanUpdateWithDelete(oldCategoryTag);
            res = this.updateById(newCategoryTag);
            ThrowUtils.throwIf(!res, ErrorCode.OPERATION_ERROR, "标签删除失败,数据库操作失败");
        }
    }

    /**
     * 判断分类是否可以被删除
     *
     * @param oldCategoryTag
     */
    private void validCategoryCanUpdateWithDelete(CategoryTag oldCategoryTag) {
        //查询是否有图片正在使用该分类
        String categoryName = oldCategoryTag.getName();
        boolean isExists = pictureService.lambdaQuery()
                .eq(Picture::getCategory, categoryName)
                .exists();
        //判断是否被使用
        if (isExists) {
            //有图片正在使用，抛出异常
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "该分类已被使用，无法修改/删除");
        }
    }

    /**
     * 获取查询对象
     *
     * @param categoryTagQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<CategoryTag> getQueryWrapper(CategoryTagQueryRequest categoryTagQueryRequest) {
        QueryWrapper<CategoryTag> queryWrapper = new QueryWrapper<>();
        if (categoryTagQueryRequest == null) {
            return queryWrapper;
        }
        // 从对象中取值
        Long id = categoryTagQueryRequest.getId();
        Integer type = categoryTagQueryRequest.getType();
        String name = categoryTagQueryRequest.getName();
        Long userId = categoryTagQueryRequest.getUserId();
        String sortField = categoryTagQueryRequest.getSortField();
        String sortOrder = categoryTagQueryRequest.getSortOrder();

        // 拼接查询条件
        queryWrapper.eq(ObjUtil.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjUtil.isNotEmpty(userId), "userId", userId);
        queryWrapper.like(StrUtil.isNotBlank(name), "name", name);
        queryWrapper.eq(ObjUtil.isNotEmpty(type), "type", type);
        // 排序
        queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), sortOrder.equals("ascend"), sortField);
        return queryWrapper;
    }
}




